const path = require('path')
const chokidar = require('chokidar')
const fs = require('fs')
const { defineConfig } = require('@vue/cli-service')
const ESLintPlugin = require('eslint-webpack-plugin')
const CompressionPlugin = require("compression-webpack-plugin")
const pkg = require('./package.json')

function setupMockServer(app) {
  const mockDir = path.join(__dirname, './mock')

  fs.readdirSync(mockDir).forEach(file => {
    let mocks = require(path.join(mockDir, file))

    function reloadMocks() {
      Object.keys(require.cache).forEach((id) => {
        if (id.includes(path.join(mockDir, file))) {
          delete require.cache[id];
        }
      });
      mocks = require(path.join(mockDir, file));
    }

    chokidar.watch(path.join(mockDir, file)).on('all', (event, filePath) => {
      if (event === 'change' || event === 'add') {
        console.log(`Mock file ${filePath} has been ${event}, reloading mock data...`);
        reloadMocks()
      }
    })

    app.use((req, res, next) => {
      const generateMocks = mocks();
      const mockResponse = generateMocks[`${req.method} ${req.path}`];
      if (mockResponse) {
        res.json(mockResponse);
      } else {
        next();
      }
    });
  })
}

const isProd = process.env.NODE_ENV === 'production'
const configureWebpackPlugins = []
// eslint文件修复
configureWebpackPlugins.push(new ESLintPlugin({
  extensions: ['js', 'vue', 'html', 'ts', 'tsx'],
  fix: true,
  emitError: true,
  emitWarning: true
}))
isProd && configureWebpackPlugins.push(new CompressionPlugin({
  test: /\.(js|css|json|html)(\?.*)?$/i,
  filename: '[path][base].gz', // 压缩后的文件名
  algorithm: 'gzip',
  threshold: 10240, // 仅处理大于此大小的资产（以字节为单位）
  minRatio: 0.8, // 仅压缩比该比率更好的资产（minRatio = Compressed Size / Original Size）
  deleteOriginalAssets: false // 是否删除原始文件
}))

module.exports = defineConfig({
  transpileDependencies: true,
  productionSourceMap: false,
  publicPath: '/{{name}}',
  devServer: {
    https: true,
    host: '{{domain}}',
    port: 443,
    proxy: isProd || process.env.VUE_APP_MOCK ? {} : {
      '/admin': {
        target: 'http://127.0.0.1:7001', // 联调时改成转发地址
        changeOrigin: true,
        secure: false,
      }
    },
    setupMiddlewares: (middlewares, devServer) => {
      if (!devServer) {
        throw new Error('webpack-dev-server is not defined')
      }
      // 本地开发启用mock
      if (process.env.VUE_APP_MOCK) {
        console.info('本地开发启用 mock 服务...')
        setupMockServer(devServer.app)
      }
      return middlewares
    }
  },
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          javascriptEnabled: true
        }
      }
    }
  },
  chainWebpack: config => {
    const cdn = {
      css: [],
      js: []
    }
    const devCdn = {
      css: [],
      js: []
    }
    config.plugin('html').tap(args => {
      args[0].cdn = isProd ? cdn : devCdn
      args[0].title = pkg.title
      args[0].version = pkg.version
      return args
    })
    if (isProd) {
      // 删除console、debugger、注释
      const terser = config.optimization.minimizer('terser')
      terser.tap(args => {
        const { terserOptions } = args[0]
        const mergeTerserOption = {
          compress: {
            ...terserOptions.compress,
            drop_console: true,
            drop_debugger: true
          },
          format: {
            comments: /@license/i
          }
        }
        Object.assign(terserOptions, mergeTerserOption)
        return args
      })
      // 分包
      config.optimization.splitChunks({
        cacheGroups: {
          common: {
            name: 'chunk-common',
            chunks: 'initial',
            minChunks: 1,
            maxInitialRequests: 5,
            minSize: 0,
            priority: 1,
            reuseExistingChunk: true
          },
          vendors: {
            name: 'chunk-vendors',
            test: /[\\/]node_modules[\\/]/,
            chunks: 'initial',
            maxSize: 600000,
            maxInitialRequests: 20,
            priority: 2,
            reuseExistingChunk: true,
            enforce: true
          },
          antDesignVue: {
            name: 'chunk-ant-design-vue',
            test: /[\\/]node_modules[\\/]ant-design-vue[\\/]/,
            chunks: 'initial',
            priority: 3,
            maxSize: 600000,
            reuseExistingChunk: true,
            enforce: true
          }
        }
      })
    }
  },
  configureWebpack: {
    plugins: configureWebpackPlugins,
    resolve: {
      alias: {
        vue: path.resolve('./node_modules/vue')
      }
    }
  }
})
